Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a new input syntax for function. #1254

Draft
wants to merge 22 commits into
base: dev
Choose a base branch
from
Draft

Conversation

DavidFangWJ
Copy link
Contributor

@DavidFangWJ DavidFangWJ commented Mar 25, 2024

Motivation

Add a more compact syntax to function, such that

let f(x : A, y: B): C = 
  e

should behave the same as below:

let f : (A, B) -> C = 
  fun (x, y) -> e

This new function syntax is more analogous to other programming languages with strong data types, and is therefore easier to learn.

Implementation Strategy

I believe that it will mostly be a modification of Form.re.

  • Add new syntax expression
  • Make sure that its further processing is identical to existing function syntax

@cyrus-
Copy link
Member

cyrus- commented Mar 26, 2024

@DavidFangWJ We shouldn't actually need to modify Form.re to accomplish this, since the syntax of patterns already includes application and annotations:

image

We will need to change how patterns in let bindings are processed in the statics and elaboration to special case the situation where the top-level pattern is x(p1[: t1], ..., pn[: tn])[ : t].

@cyrus- cyrus- marked this pull request as draft March 27, 2024 02:57
@cyrus- cyrus- added the in-development for PRs that remain in development label Mar 29, 2024
@cyrus-
Copy link
Member

cyrus- commented Apr 12, 2024

Regarding the type error, take a look at the definition of UPat.t -- it is a record type, because terms have unique IDs, so you need to decompose it like the other functions working on UPat's do.

Regarding the function itself, you should be looking for the application of a variable, rather than a constructor. Constructors are capitalized.

You also do not need to check that all arguments have type annotations -- it is okay to leave an argument unannotated, it will just get the unknown type.

You also need to handle optional return type annotations (which will require changing the return type of your function overall).

Please write some additional examples in your PR message to handle both functions with missing type annotations on arguments and missing return types, so make it clear these are all valid. We'll turn these into tests as well.

src/haz3lcore/statics/Statics.re Outdated Show resolved Hide resolved
@DavidFangWJ DavidFangWJ self-assigned this Apr 24, 2024
@DavidFangWJ
Copy link
Contributor Author

Cannot fully understand the part in Statics.re/uexp_to_info_map regarding the process of let binding, which looks like this:

  | Let(p, def, body) =>
    let (p_syn, _) =
      go_pat(~is_synswitch=true, ~co_ctx=CoCtx.empty, ~mode=Syn, p, m);
    let (def, p_ana_ctx, m, ty_p_ana) =
      if (!is_recursive(ctx, p, def, p_syn.ty)) {
        let (def, m) = go(~mode=Ana(p_syn.ty), def, m);
        let ty_p_ana = def.ty;
        let (p_ana', _) =
          go_pat(
            ~is_synswitch=false,
            ~co_ctx=CoCtx.empty,
            ~mode=Ana(ty_p_ana),
            p,
            m,
          );
        (def, p_ana'.ctx, m, ty_p_ana);
      } else {
        let (def_base, _) =
          go'(~ctx=p_syn.ctx, ~mode=Ana(p_syn.ty), def, m);
        let ty_p_ana = def_base.ty;
        /* Analyze pattern to incorporate def type into ctx */
        let (p_ana', _) =
          go_pat(
            ~is_synswitch=false,
            ~co_ctx=CoCtx.empty,
            ~mode=Ana(ty_p_ana),
            p,
            m,
          );
        let def_ctx = p_ana'.ctx;
        let (def_base2, _) = go'(~ctx=def_ctx, ~mode=Ana(p_syn.ty), def, m);
        let ana_ty_fn = ((ty_fn1, ty_fn2), ty_p) => {
          ty_p == Typ.Unknown(SynSwitch) && !Typ.eq(ty_fn1, ty_fn2)
            ? ty_fn1 : ty_p;
        };
        let ana =
          switch ((def_base.ty, def_base2.ty), p_syn.ty) {
          | ((Prod(ty_fns1), Prod(ty_fns2)), Prod(ty_ps)) =>
            let tys =
              List.map2(ana_ty_fn, List.combine(ty_fns1, ty_fns2), ty_ps);
            Typ.Prod(tys);
          | ((ty_fn1, ty_fn2), ty_p) => ana_ty_fn((ty_fn1, ty_fn2), ty_p)
          };
        let (def, m) = go'(~ctx=def_ctx, ~mode=Ana(ana), def, m);
        (def, def_ctx, m, ty_p_ana);
      };
    let (body, m) = go'(~ctx=p_ana_ctx, ~mode, body, m);
    /* add co_ctx to pattern */
    let (p_ana, m) =
      go_pat(
        ~is_synswitch=false,
        ~co_ctx=body.co_ctx,
        ~mode=Ana(ty_p_ana),
        p,
        m,
      );
    add(
      ~self=Just(body.ty),
      ~co_ctx=
        CoCtx.union([def.co_ctx, CoCtx.mk(ctx, p_ana.ctx, body.co_ctx)]),
      m,
    );

@cyrus-
Copy link
Member

cyrus- commented Aug 20, 2024

@DavidFangWJ there is a small merge conflict + the following has an error on f:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-development for PRs that remain in development
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants